// Copyright (c) Appeon. All rights reserved.
// Licensed under the Apache License, Version 2.0 (the "License"); you may not use this file except in compliance with the License. 
// You may obtain a copy of the License at http://www.apache.org/licenses/LICENSE-2.0.

using System;
using System.Collections.Concurrent;
using System.Collections.Generic;
using System.Linq.Expressions;
using Microsoft.Extensions.DependencyInjection;

namespace SnapObjects.Expressions
{
    internal class NestParseProvider<T> : INestParseProvider<T>
    {
        private readonly IDictionary<string, INestParseProvider<T>> _providers;

        public NestParseProvider(IServiceProvider services)
        {
            _providers = new ConcurrentDictionary<string, INestParseProvider<T>>();

            var providers = services.GetServices<INestParseProvider<T>>();

            foreach (var provider in providers)
            {
                foreach (var kind in provider.SupportKinds)
                {
                    _providers[kind] = provider;
                }
            }
        }

        public string[] SupportKinds { get; }

        public ParserOptions<Expression> CreateOptions(ParserOptions<T> options)
        {
            var parser = this.Get(options.SourceKind);

            return parser.CreateOptions(options);
        }

        public T Invoke(ParserOptions<T> options, Expression nestExpression, ParserOptions<Expression> nestOptions)
        {
            var parser = this.Get(options.SourceKind);

            return parser.Invoke(options, nestExpression, nestOptions);
        }

        private INestParseProvider<T> Get(string sourceKind)
        {
            if (_providers.TryGetValue(sourceKind, out var provider))
            {
                return provider;
            }

            throw new NotSupportedException($"NestParse: {sourceKind}");
        }
    }
}
